import { MedicalDocument,FhirDocumentReference, MedicalElement, MedicalText, MedicalElementType } from '../types/medicalTypes';

/**
 * 章节类型与LOINC编码映射
 */
const SECTION_TYPE_TO_LOINC: Record<string, string> = {
  'chief-complaint': '11348-9',      // 主诉
  'present-illness': '11349-7',     // 现病史
  'past-medical-history': '27167-4', // 既往史
  'family-history': '48865-2',       // 家族史
  'physical-exam': '7420-4',         // 体格检查
  'diagnosis': '55101-6',            // 诊断
  'treatment-plan': '28570-0',       // 治疗计划
  'medication': '10160-0',           // 用药
  'laboratory-test': '30954-2',      // 实验室检查
  'imaging-study': '18776-5'         // 影像学检查
};

/**
 * LOINC编码到章节类型映射
 */
const LOINC_TO_SECTION_TYPE: Record<string, string> = Object.entries(
  SECTION_TYPE_TO_LOINC
).reduce((acc, [type, code]) => {
  acc[code] = type;
  return acc;
}, {} as Record<string, string>);

/**
 * 将医疗文档转换为FHIR DocumentReference格式
 * @param document 医疗文档
 * @returns FHIR DocumentReference资源
 */
 export function toFhirFormat(document: MedicalElement[]): FhirDocumentReference {
    return {
      resourceType: 'DocumentReference',
      content: document.map(element => ({
        title: element.type,
        attachment: {
          data: btoa(JSON.stringify(element)),
          creation: new Date().toISOString()
        },
        type: {
          coding: [{
            code: SECTION_TYPE_TO_LOINC[element.type] || 'unknown'
          }]
        }
      }))
    };
  }

/**
 * 从FHIR格式解析为医疗文档
 * @param fhirData FHIR DocumentReference资源
 * @returns 医疗文档
 */
 export const fromFhirFormat = (fhirData: FhirDocumentReference): MedicalDocument => {
    return fhirData.content.map(item => {
      try {
        const decodedData = atob(item.attachment.data || '');
        const element = JSON.parse(decodedData) as MedicalElement;
        
        const sectionType = (LOINC_TO_SECTION_TYPE[
          item.type?.coding?.[0]?.code || 'unknown'
        ] || element.type) as MedicalElementType;
        
        return {
          ...element,
          type: sectionType,
          medical: {
            ...element.medical,
            sectionCode: item.type?.coding?.[0]?.code || 'unknown',
            updateTime: item.attachment.creation || new Date().toISOString()
          },
          children: element.children
        };
      } catch (error) {
        console.error('解析FHIR内容失败:', error);
        return {
          type: 'paragraph',
          children: [{ text: '内容解析失败' }]
        };
      }
    });
  };

/**
 * 获取章节显示标题
 * @param type 章节类型
 * @returns 显示标题
 */
export const getSectionTitle = (type: string): string => {
  const titles: Record<string, string> = {
    'heading': '标题',
    'paragraph': '段落',
    'chief-complaint': '主诉',
    'present-illness': '现病史',
    'past-medical-history': '既往史',
    'family-history': '家族史',
    'physical-exam': '体格检查',
    'diagnosis': '诊断',
    'treatment-plan': '治疗计划',
    'medication': '用药',
    'laboratory-test': '实验室检查',
    'imaging-study': '影像学检查'
  };
  
  return titles[type] || type;
};

/**
 * 验证医疗文档结构完整性
 * @param document 医疗文档
 * @returns 验证结果
 */
export const validateDocument = (document: MedicalDocument): {
  valid: boolean;
  missingSections?: string[];
} => {
  const requiredSections = ['chief-complaint', 'present-illness', 'diagnosis'];
  const missingSections = requiredSections.filter(
    section => !document.some(element => element.type === section)
  );
  
  return {
    valid: missingSections.length === 0,
    missingSections
  };
};

/**
 * 提取文档中的所有医学术语
 * @param document 医疗文档
 * @returns 医学术语列表
 */
export const extractMedicalTerms = (document: MedicalDocument): string[] => {
  const terms: string[] = [];
  
  document.forEach(element => {
    element.children.forEach(node => {
      if (isMedicalText(node) && node.text && node.medical?.medicalTerm) {
        terms.push(node.text);
      }
    });
  });
  
  return [...new Set(terms)]; // 去重
};

/**
 * 计算文档统计信息
 * @param document 医疗文档
 * @returns 统计信息
 */
export const calculateDocumentStats = (document: MedicalDocument): {
  wordCount: number;
  sectionCount: number;
  updateTime?: string;
} => {
    const wordCount = document.reduce((count, element) => {
        return count + element.children.reduce((textCount, node) => {
          return textCount + (isMedicalText(node) ? (node.text?.length || 0) : 0);
        }, 0);
      }, 0);
  
  const sectionCount = document.length;
  
  // 获取最新更新时间
  const updateTimes = document
    .map(element => element.medical?.updateTime)
    .filter(Boolean) as string[];
  
  const latestUpdateTime = updateTimes.length > 0
    ? new Date(Math.max(...updateTimes.map(time => new Date(time).getTime()))).toISOString()
    : undefined;
  
  return {
    wordCount,
    sectionCount,
    updateTime: latestUpdateTime
  };
};

// Add type guard for MedicalText
function isMedicalText(node: MedicalElement | MedicalText): node is MedicalText {
  return 'text' in node;
}
